package com.ailargemodel.service.impl;

import com.ailargemodel.common.BaseResponse;
import com.ailargemodel.common.ErrorCode;
import com.ailargemodel.common.utils.ResultUtil;
import com.ailargemodel.mapper.QuesttionMapper;
import com.ailargemodel.mapper.UserMapper;
import com.ailargemodel.pojo.Questtion;
import com.ailargemodel.pojo.User;
import com.ailargemodel.service.RankListService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class RankListServiceImpl implements RankListService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private QuesttionMapper questtionMapper;


    @Autowired
    private RedisTemplate redisTemplate;

    public final static String SCORE_RANK = "score_rank";


    /**
     * 插入 数据
     * @return
     */
    @Override
//  每晚 2:00准时跟新
    @Scheduled(cron = "0 0 2 * * *")
    public BaseResponse insertRankList() {
        List<User> userList = userMapper.selectAll();
        Set<ZSetOperations.TypedTuple<User>> tuples = new HashSet<>();
//        long start = System.currentTimeMillis();
        for (User user : userList) {
            DefaultTypedTuple<User> tuple = new DefaultTypedTuple<>(user,calculateScore(user));
            tuples.add(tuple);
        }
//        log.info("循环时间:"+(System.currentTimeMillis() - start));
        Long num = redisTemplate.opsForZSet().add(SCORE_RANK, tuples);
        redisTemplate.expire(SCORE_RANK,1l, TimeUnit.DAYS);
//        log.info("批量导入新增时间:" + (System.currentTimeMillis() - start));
//        log.info("受影响的行数"+ num);

        return null;
    }

    /**
     * 获取总的排行榜
     * @return
     */
    public BaseResponse getRankList() {
        Set<User> range = redisTemplate.opsForZSet().reverseRange(SCORE_RANK,0,100);
        Gson gson = new Gson();
//        log.info("获取到的排行榜表:"+gson.toJson(range));
        Set<ZSetOperations.TypedTuple<User>> rangeWithScores = redisTemplate.opsForZSet().reverseRangeWithScores(SCORE_RANK,0,100);
//        log.info("获取到的排行和分数列表:"+ gson.toJson(rangeWithScores));

        return ResultUtil.sucess(rangeWithScores);
    }

    /**
     * 获取单个人物的 排名
     * @param user
     * @return
     */
    public BaseResponse getSingleRank(User user) {
//        TODO have 不能显示的 bug
//        User singleUser = query().eq("study_id",user.getStudyId()).one();
        BaseResponse rankList = getRankList();
        Set<ZSetOperations.TypedTuple<User>> data = (Set<ZSetOperations.TypedTuple<User>>) rankList.getData();
        int num = 0;
        for (ZSetOperations.TypedTuple<User> datum : data) {
            num ++;
            if (datum.getValue().getStudyId().equals(user.getStudyId())){
//                log.info(user.getName() + "的个人排名：" + num);
//                log.info(user.getName() + "的分数:" + datum.getScore());
                return ResultUtil.sucess(num,datum.getScore());
            }
        }

        return ResultUtil.error(ErrorCode.SYSTEM_ERROR);
    }

    private Double  calculateScore(User user){
//      有个活跃指数 (询问次数 0.7, 评价次数 0.3, 等等)
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("study_id",user.getStudyId());
        List<Questtion> questionList = questtionMapper.selectList(queryWrapper);
        int gradeNum = 0, maxQuestionNum = 0;
        for (Questtion questtion : questionList) {
            if (questtion.getGrade() != 0)  gradeNum ++;
            if (questtion.getQuestionId() >= maxQuestionNum) maxQuestionNum = questtion.getQuestionId();
        }
        return 0.7*maxQuestionNum + 0.3*gradeNum;
    }
}
